package com.dotflat.agreement.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aspose.words.*;
import com.dotflat.agreement.domain.OPAgreement;
import com.dotflat.agreement.domain.OPAgreementRecord;
import com.dotflat.agreement.po.OPAgreementRecordPO;
import com.dotflat.agreement.repository.OPAgreementRecordRepository;
import com.dotflat.agreement.repository.OPAgreementRepository;
import com.dotflat.agreement.service.OPAgreementRecordService;
import com.dotflat.rest.PO.AreableObjectBasePO;
import com.dotflat.rest.service.impl.AreableObjectBaseServiceImpl;
import com.dotflat.util.Base64ToFile;
import com.matt.commons.exception.BusinessException;
import com.matt.foundation.model.ErrorCode;
import com.matt.service.UploadService;
import com.tuo51.foudation.utils.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;


@Service
public class OPAgreementRecordServiceImpl extends AreableObjectBaseServiceImpl<OPAgreementRecord, OPAgreementRecordRepository>
        implements OPAgreementRecordService {

    @Autowired
    @Override
    public void setBaseRepository(OPAgreementRecordRepository repository){
        super.setBaseRepository(repository);
    }

    @Autowired
    private OPAgreementRepository agreementRepository;

    @Autowired
    private UploadService uploadService;

    @Override
    public Page<OPAgreementRecord> page(String areaId, String staffId, AreableObjectBasePO param, PageRequest pageRequest) {

        if (StringUtils.isNotBlank(areaId)) {
            param.setAreaId(areaId);
        }
        param.setDeleted(false);

        List<OPAgreement> agreements = agreementRepository.findAllValidItemsByRecordNotExist(areaId, staffId);

        if (agreements.size() > 0){
            //创建record
            List<OPAgreementRecord> records = agreements.stream().map(o->{
                OPAgreementRecord record = new OPAgreementRecord();
                record.setAgreementId(o.getId());
                record.setAreaId(areaId);
                record.setCreatedBy(staffId);
                return record;
            }).collect(Collectors.toList());

            baseRepository.saveAll(records);
        }

        return super.page(areaId, staffId, param, pageRequest);
    }

    @Override
    public OPAgreementRecord add(String areaId, String staffId, AreableObjectBasePO param, Consumer<? super OPAgreementRecord> preAction) {

        OPAgreementRecord record = super.add(areaId, staffId, param, preAction);

        OPAgreement agreement = record.getAgreement();
        if (agreement == null) {
            throw new BusinessException(ErrorCode.MATERIAL_NOT_EXIST, "授权文档不存在");
        }

        if (param instanceof OPAgreementRecordPO){
            //创建
            OPAgreementRecordPO p = (OPAgreementRecordPO)param;

            if (StringUtils.isNotEmpty(p.getSignImageBase64()) && StringUtils.isBlank(record.getStaticUrl())){

                //上传sign
                String type = "agreement/" + DateUtil.getToday();
                MultipartFile file = Base64ToFile.base64ToMultipartFile(p.getSignImageBase64(), staffId + "_sign.png");
                String uploaded_sign = uploadService.uploadCommonFile(staffId, type, file);

                //获取agreement

                //下载模板
                JSONObject customParams =  JSON.parseObject(p.getContent());
                //上传sso， 创建静态文件
                String docFile = processFile(staffId, agreement.getStaticUrl(), p.getSignImageBase64(), customParams);

                record.setStaticUrl(docFile);
                record.setSignUrl(uploaded_sign);

                baseRepository.save(record);
            }


        }

        return record;
    }

    private String processFile(String staffId, String templateURL, String base64Image, Map param) {
        try {
            return processFileLogic(staffId, templateURL, base64Image, param);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.FILE_MAST_NOT_NULL, "创建文件时异常");
        }
    }


    private String processFileLogic(String staffId, String templateURL, String base64Image, Map param) throws Exception {

        // 创建一个Web请求，下载文档内容
        Document doc = null;
        InputStream inputStream = null;
        try {
            URL url = new URL(templateURL);
            inputStream = url.openStream();

            // 加载文档
            doc = new Document(inputStream);

        }catch (IOException e){
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SSO_CALL_ERROR, "获取协议模板失败");
        }finally {
            // 关闭输入流
            inputStream.close();
        }

        // 现在可以在内存中操作文档了
        //替换文字和图片
        BufferedImage image = Base64ToFile.decodeToImage(base64Image);
        replaceSignImage(doc, image);

        if (param != null) {
            Set keys = param.keySet();
            for (Object key : keys) {
                String keyStr = key.toString();

                String value = param.get(key).toString();

                replaceParams(doc, String.format("{%s}", keyStr), value);
            }
        }


        // 保存文档到本地或进行其他操作
        String tempFileName = "/tmp/" + staffId + "_" + System.currentTimeMillis() + ".docx";
        doc.save(tempFileName );

        //上传本地文件
        String static_file_url = uploadService.uploadLocalFile(tempFileName, "static_agreement");

        return static_file_url;
    }

    private void replaceSignImage(Document doc, BufferedImage image){
        // 遍历文档中的所有节点，查找图片
        try {
            NodeCollection shapes = doc.getChildNodes(NodeType.SHAPE, true);
            for (Shape shape : (Iterable<Shape>) shapes) {

                if (shape.hasImage()) {
                    // 找到图片，可以进行替换操作
                    shape.getImageData().setImage(image);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void replaceParams(Document doc, String findTxt, String replaceTxt){
        FindReplaceOptions options = new FindReplaceOptions();

        try {
            doc.getRange().replace(findTxt, replaceTxt, options);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}